package com.example.util;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Hashtable;
import java.util.Map;

public class QrCodeUtil {

    /**
     * 二维码颜色
     */
    private static final int BLACK = 0xFF000000;
    private static final int WHITE = 0xFFFFFFFF;
    /**
     * LOGO宽度
     */
    private static final int LOGO_WIDTH = 60;
    /**
     * LOGO高度
     */
    private static final int LOGO_HEIGHT = 60;
    /**
     * 图片的宽度
     */
    private static int WIDTH = 300;
    /**
     * 图片的高度
     */
    private static int HEIGHT = 300;
    /**
     * 图片的格式
     */
    private static String FORMAT = "png";

    /**
     * 生成二维码(内嵌LOGO---OutputStream)
     *
     * @param content      内容
     * @param logoPath     LOGO地址
     * @param output       输出流
     * @param needCompress 是否压缩LOGO
     * @throws Exception
     */
    public static void encode(String content, String logoPath, OutputStream output, boolean needCompress)
            throws Exception {
        BufferedImage image = QrCodeUtil.createImage(content, logoPath, needCompress);
        ImageIO.write(image, FORMAT, output);
    }

    /**
     * 生成二维码(不内嵌LOGO)
     *
     * @param content 内容
     * @param outPath LOGO地址
     * @throws Exception
     */
    public static void createCode(String content, String outPath) {
        try {
            BufferedImage bufferedImage = QrCodeUtil.createImage(content, "", false);
            File file = new File(outPath);
            if (!file.exists() && !file.isDirectory()) {
                file.mkdirs();
            }
            String name = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
            String realPath = file.getPath() + name + "." + FORMAT;
            File outputFile = new File(realPath);
            ImageIO.write(bufferedImage, FORMAT, outputFile);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }


    /**
     * 生成二维码(内嵌LOGO)
     *
     * @param content 内容
     * @param outPath LOGO地址
     * @throws Exception
     */
    public static void createCodeToLogo(String content, String outPath, String logoPath, boolean needCompress) {
        try {
            BufferedImage bufferedImage = QrCodeUtil.createImage(content, logoPath, needCompress);
            File file = new File(outPath);
            if (!file.exists() && !file.isDirectory()) {
                file.mkdirs();
            }
            String name = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
            String realPath = file.getPath() + name + "." + FORMAT;
            File outputFile = new File(realPath);
            ImageIO.write(bufferedImage, FORMAT, outputFile);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    /**
     * 生成二维码
     *
     * @param content      二维码内容
     * @param logoPath     图片地址
     * @param needCompress 是否压缩logo
     * @return
     */
    public static BufferedImage createImage(String content, String logoPath, boolean needCompress) {
        try {
            Map<EncodeHintType, Object> encodeMap = new Hashtable<>();
            // 字符编码
            encodeMap.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            //设置二维码的纠错级别参数   //  创建一个矩阵
            BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, WIDTH, HEIGHT, encodeMap);
            // 生成二维码
            int width = bitMatrix.getWidth();
            int height = bitMatrix.getHeight();
            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
            for (int i = 0; i < width; i++) {
                for (int i1 = 0; i1 < height; i1++) {
                    image.setRGB(i, i1, bitMatrix.get(i, i1) ? BLACK : WHITE);
                }
            }
            if (logoPath == null || "".equals(logoPath)) {
            } else {
                // 插入图片
                QrCodeUtil.insertLoge(image, logoPath, needCompress);
            }
            return image;
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    public static void insertLoge(BufferedImage sourceImage, String logoPath, Boolean needCompress) {
        InputStream inputStream = null;
        try {
            inputStream = QrCodeUtil.getResourceAsStream(logoPath);
            Image logoImage = ImageIO.read(inputStream);
            int width = logoImage.getWidth(null);
            int height = logoImage.getHeight(null);
            if (needCompress) { // 压缩 logo
                if (width > LOGO_WIDTH) {
                    width = LOGO_WIDTH;
                }
                if (height > LOGO_HEIGHT) {
                    height = LOGO_HEIGHT;
                }
                Image image = logoImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
                BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
                Graphics graphics = bufferedImage.getGraphics();
                graphics.drawImage(image, 0, 0, null); // 绘制缩小后的图
                graphics.dispose();
                logoImage = image;
            }
            // 插入logo
            Graphics2D graphics2D = sourceImage.createGraphics();
            int x = (WIDTH - width) / 2;
            int y = (HEIGHT - height) / 2;
            graphics2D.drawImage(logoImage, x, y, width, height, null); // 压缩图片
            Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);
            graphics2D.setStroke(new BasicStroke(3f));
            graphics2D.draw(shape);
            graphics2D.dispose();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public static InputStream getResourceAsStream(String filePath) throws FileNotFoundException {
        File file = new File(filePath);
        InputStream inputStream = new FileInputStream(file);
//        return QrCodeUtil.class.getResourceAsStream(filePath);
        return inputStream;
    }

}
